package de.bloxel.controller;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrBuilder;

import de.bloxel.ui.BloxelApplication;

/**
 * @since 0.1.0
 * @author Klaus Hauschild
 */
public class BloxelConsoleAPI {

  private static final List<String> commands;

  static {
    commands = new ArrayList<String>();
    for (final Method method : BloxelConsoleAPI.class.getMethods()) {
      final BloxelConsoleAPIMethod bloxelConsoleAPIMethod = method.getAnnotation(BloxelConsoleAPIMethod.class);
      if (bloxelConsoleAPIMethod != null) {
        final StrBuilder commandBuilder = new StrBuilder();
        commandBuilder.append(method.getName());
        commandBuilder.append("(");
        final List<String> parameters = new ArrayList<String>();
        for (final Class<?> parameter : method.getParameterTypes()) {
          parameters.add(parameter.getSimpleName());
        }
        commandBuilder.appendWithSeparators(parameters, ", ");
        commandBuilder.append(")");
        // commandBuilder.append(" : ");
        // commandBuilder.append(method.getReturnType().getSimpleName());
        final String documentation = bloxelConsoleAPIMethod.value();
        if (StringUtils.isNotBlank(documentation)) {
          commandBuilder.append(" - ");
          commandBuilder.append(documentation);
        }
        commands.add(commandBuilder.toString());
      }
    }
  }

  private final BloxelApplication bloxelApplication;

  @Documented
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.METHOD)
  @interface BloxelConsoleAPIMethod {
    String value() default "";
  }

  public BloxelConsoleAPI(final BloxelApplication theBloxelApplication) {
    bloxelApplication = theBloxelApplication;
  }

  @BloxelConsoleAPIMethod("Sets the interaction range. Values below zero results in infinite range.")
  public void interactionRange(final int range) {
    bloxelApplication.setInteractionRange(range);
  }

  @BloxelConsoleAPIMethod("Prints this message.")
  public List<String> help() {
    final List<String> text = new ArrayList<String>();
    text.add("The following commands are available:");
    for (final String command : BloxelConsoleAPI.getAllCommands()) {
      text.add(String.format("  %s", command));
    }
    return text;
  }

  public static List<String> getAllCommands() {
    return commands;
  }

}
